//
// Copyright (C) 2011 Steve Channell steve.channell@cepheis.com
//
// This file is part of Cephei.QL, an open-source library wrapper 
// arround QuantLib http://quantlib.org/
//
// Cephei.QL is open source software: you can redistribute it and/or modify it
// under the terms of the license.  You should have received a
// copy of the license along with this program; if not, please email
// <support@cepheis.com>. The license is also available online at
// <http://cepheis.com/license.htm>.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the license for more details.
//
// Version 2.101
//#include "stdafx.h"
#include "CTSMMCapletMaxHomogeneityCalibration.h"
using namespace Cephei::QL::Models::Marketmodels::Models;
#include <gen/QL/Models/Marketmodels/EvolutionDescription.h>
#include <gen/QL/Models/Marketmodels/PiecewiseConstantCorrelation.h>
#include <gen/QL/Models/Marketmodels/Models/PiecewiseConstantVariance.h>
#include <gen/QL/Models/Marketmodels/CurveState.h>
#include <gen/QL/Math/Matrix.h>
#include <gen/QL/Models/Marketmodels/Models/CTSMMCapletCalibration.h>
using namespace Cephei::QL::Models::Marketmodels;
using namespace Cephei::QL::Math;
#undef HANDLE
#undef ABSTRACT
#undef STRUCT
Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::CCTSMMCapletMaxHomogeneityCalibration (Cephei::QL::Models::Marketmodels::IEvolutionDescription^ evolution, Cephei::QL::Models::Marketmodels::IPiecewiseConstantCorrelation^ corr, Cephei::IVector<Cephei::QL::Models::Marketmodels::Models::IPiecewiseConstantVariance^>^ displacedSwapVariances, Cephei::IVector<Double>^ capletVols, Cephei::QL::Models::Marketmodels::ICurveState^ cs, Double displacement, Microsoft::FSharp::Core::FSharpOption<Double>^ caplet0Swaption1Priority) : CCTSMMCapletCalibration(CCTSMMCapletMaxHomogeneityCalibration::typeid)
{
    CEvolutionDescription^ _Cevolution;
    CPiecewiseConstantCorrelation^ _Ccorr;
    CoVector<Cephei::QL::Models::Marketmodels::Models::IPiecewiseConstantVariance^>^ _CdisplacedSwapVariances;
    CoVector<Double>^ _CcapletVols;
    CCurveState^ _Ccs;
    try
    {
#ifdef HANDLE
        _phCTSMMCapletMaxHomogeneityCalibration = NULL;
#endif
        _Cevolution = safe_cast<CEvolutionDescription^> (evolution);
        _Cevolution->Lock();
        QuantLib::EvolutionDescription& _evolution = static_cast<QuantLib::EvolutionDescription&> (_Cevolution->GetReference ()); 
        _Ccorr = safe_cast<CPiecewiseConstantCorrelation^> (corr);
        _Ccorr->Lock();
        boost::shared_ptr<QuantLib::PiecewiseConstantCorrelation>& _corr = static_cast<boost::shared_ptr<QuantLib::PiecewiseConstantCorrelation>&> (_Ccorr->GetShared ()); 
        _CdisplacedSwapVariances = safe_cast<CoVector<Cephei::QL::Models::Marketmodels::Models::IPiecewiseConstantVariance^>^> (displacedSwapVariances);
        _CdisplacedSwapVariances ->Lock ();
        INativeVector<Cephei::QL::Models::Marketmodels::Models::IPiecewiseConstantVariance^>^ _NCIdisplacedSwapVariances = _CdisplacedSwapVariances->getFeature (NativeFeature::shared_ptr);
        CPiecewiseConstantVarianceVector^ _NCdisplacedSwapVariances = safe_cast<CPiecewiseConstantVarianceVector^>(_NCIdisplacedSwapVariances);
        std::vector<boost::shared_ptr<
                        QuantLib::PiecewiseConstantVariance> >& _displacedSwapVariances = static_cast<std::vector<boost::shared_ptr<
                        QuantLib::PiecewiseConstantVariance> >&> (_NCdisplacedSwapVariances->GetShared ());
        CoVector<Double>^ _CcapletVols = safe_cast<CoVector<Double>^> (capletVols);
        _CcapletVols->Lock();
        INativeVector<Double>^ _NCIcapletVols = _CcapletVols->getFeature (NativeFeature::Value);
        CDoubleVector^ _NCcapletVols = safe_cast<CDoubleVector^>(_NCIcapletVols);
        std::vector<QuantLib::Volatility>& _capletVols = static_cast<std::vector<QuantLib::Volatility>&> (_NCcapletVols->GetReference ());
        _Ccs = safe_cast<CCurveState^> (cs);
        _Ccs->Lock();
        boost::shared_ptr<QuantLib::CurveState>& _cs = static_cast<boost::shared_ptr<QuantLib::CurveState>&> (_Ccs->GetShared ()); 
        QuantLib::Spread _displacement = (QuantLib::Spread)ValueHelper::Convert (displacement);
        QuantLib::Real _caplet0Swaption1Priority = 
            (Microsoft::FSharp::Core::FSharpOption<Double>::IsSome::get (caplet0Swaption1Priority) ? (QuantLib::Real)ValueHelper::Convert (caplet0Swaption1Priority->Value) : 1.0); //4
        _ppCTSMMCapletMaxHomogeneityCalibration = new boost::shared_ptr<QuantLib::CTSMMCapletMaxHomogeneityCalibration> (new QuantLib::CTSMMCapletMaxHomogeneityCalibration ( _evolution,  _corr,  _displacedSwapVariances,  _capletVols,  _cs,  _displacement,  _caplet0Swaption1Priority ));
        SetCTSMMCapletCalibration (boost::dynamic_pointer_cast<QuantLib::CTSMMCapletCalibration> (*_ppCTSMMCapletMaxHomogeneityCalibration));
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown std::exception"));
	}
    finally
    {
        if (_Cevolution != nullptr) _Cevolution->Unlock();
        if (_Ccorr != nullptr) _Ccorr->Unlock();
        if (_CdisplacedSwapVariances != nullptr) _CdisplacedSwapVariances->Unlock();
        if (_CcapletVols != nullptr) _CcapletVols->Unlock();
        if (_Ccs != nullptr) _Ccs->Unlock();
    }
}
Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::CCTSMMCapletMaxHomogeneityCalibration (boost::shared_ptr<QuantLib::CTSMMCapletMaxHomogeneityCalibration>& childNative, Object^ owner) : CCTSMMCapletCalibration(CCTSMMCapletMaxHomogeneityCalibration::typeid)
{
#ifdef HANDLE
	_phCTSMMCapletMaxHomogeneityCalibration = NULL;
#endif
	_ppCTSMMCapletMaxHomogeneityCalibration = &childNative;
    _ppCTSMMCapletCalibration = new boost::shared_ptr<QuantLib::CTSMMCapletCalibration> (boost::dynamic_pointer_cast<QuantLib::CTSMMCapletCalibration> (*_ppCTSMMCapletMaxHomogeneityCalibration));
}
Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::CCTSMMCapletMaxHomogeneityCalibration (QuantLib::CTSMMCapletMaxHomogeneityCalibration& childNative, Object^ owner) : CCTSMMCapletCalibration(CCTSMMCapletMaxHomogeneityCalibration::typeid)
{
#ifdef HANDLE
	_phCTSMMCapletMaxHomogeneityCalibration = NULL;
#endif
	_ppCTSMMCapletMaxHomogeneityCalibration = new boost::shared_ptr<QuantLib::CTSMMCapletMaxHomogeneityCalibration> (&childNative);
    _ppCTSMMCapletCalibration = new boost::shared_ptr<QuantLib::CTSMMCapletCalibration> (boost::dynamic_pointer_cast<QuantLib::CTSMMCapletCalibration> (*_ppCTSMMCapletMaxHomogeneityCalibration));
    _CTSMMCapletMaxHomogeneityCalibrationOwner = owner;
    _CTSMMCapletCalibrationOwner = owner;
}

Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::CCTSMMCapletMaxHomogeneityCalibration (CCTSMMCapletMaxHomogeneityCalibration^ copy) : CCTSMMCapletCalibration(CCTSMMCapletMaxHomogeneityCalibration::typeid)
{
#ifdef HANDLE
	_phCTSMMCapletMaxHomogeneityCalibration = NULL;
#endif
	if (copy->HasNative() != NULL)
    {
		_ppCTSMMCapletMaxHomogeneityCalibration = new boost::shared_ptr<QuantLib::CTSMMCapletMaxHomogeneityCalibration> (copy->GetShared());
        _ppCTSMMCapletCalibration = new boost::shared_ptr<QuantLib::CTSMMCapletCalibration> (boost::dynamic_pointer_cast<QuantLib::CTSMMCapletCalibration> (*_ppCTSMMCapletMaxHomogeneityCalibration));
    }
}
Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::CCTSMMCapletMaxHomogeneityCalibration (System::Type^ t) : CCTSMMCapletCalibration(CCTSMMCapletMaxHomogeneityCalibration::typeid)
{
#ifdef HANDLE
	_phCTSMMCapletMaxHomogeneityCalibration = NULL;
#endif
	if (!t->IsSubclassOf(CCTSMMCapletMaxHomogeneityCalibration::typeid))
		throw gcnew Exception ("Invalid base-case init");
}
#ifdef HANDLE
Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::CCTSMMCapletMaxHomogeneityCalibration (QuantLib::Handle<QuantLib::CTSMMCapletMaxHomogeneityCalibration>& childNative, Object^ owner)  : CCTSMMCapletCalibration(CCTSMMCapletMaxHomogeneityCalibration::typeid)
{
	_phCTSMMCapletMaxHomogeneityCalibration = &childNative;
	_ppCTSMMCapletMaxHomogeneityCalibration = &static_cast<boost::shared_ptr<QuantLib::CTSMMCapletMaxHomogeneityCalibration>>(childNative.currentLink());
    _ppCTSMMCapletCalibration = new boost::shared_ptr<QuantLib::CTSMMCapletCalibration> (boost::dynamic_pointer_cast<QuantLib::CTSMMCapletCalibration> (*_ppCTSMMCapletMaxHomogeneityCalibration));
    _CTSMMCapletMaxHomogeneityCalibrationOwner = owner;
}
Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::CCTSMMCapletMaxHomogeneityCalibration (QuantLib::Handle<QuantLib::CTSMMCapletMaxHomogeneityCalibration> childNative)  : CCTSMMCapletCalibration(CCTSMMCapletMaxHomogeneityCalibration::typeid)
{
	_phCTSMMCapletMaxHomogeneityCalibration = &childNative;
	_ppCTSMMCapletMaxHomogeneityCalibration = &static_cast<boost::shared_ptr<QuantLib::CTSMMCapletMaxHomogeneityCalibration>>(childNative.currentLink());
    _ppCTSMMCapletCalibration = new boost::shared_ptr<QuantLib::CTSMMCapletCalibration> (boost::dynamic_pointer_cast<QuantLib::CTSMMCapletCalibration> (*_ppCTSMMCapletMaxHomogeneityCalibration));
}
#endif
#ifdef STRUCT
Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::CCTSMMCapletMaxHomogeneityCalibration (QuantLib::CTSMMCapletMaxHomogeneityCalibration childNative)  : CCTSMMCapletCalibration(CCTSMMCapletMaxHomogeneityCalibration::typeid)
{
#ifdef HANDLE
	_phCTSMMCapletMaxHomogeneityCalibration = NULL;
#endif
	_ppCTSMMCapletMaxHomogeneityCalibration = new boost::shared_ptr<QuantLib::CTSMMCapletMaxHomogeneityCalibration> (new QuantLib::CTSMMCapletMaxHomogeneityCalibration (childNative));
    _ppCTSMMCapletCalibration = new boost::shared_ptr<QuantLib::CTSMMCapletCalibration> (boost::dynamic_pointer_cast<QuantLib::CTSMMCapletCalibration> (*_ppCTSMMCapletMaxHomogeneityCalibration));
}
#endif

Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::~CCTSMMCapletMaxHomogeneityCalibration ()
{
    if (_ppCTSMMCapletMaxHomogeneityCalibration != NULL)
    {
	    delete _ppCTSMMCapletMaxHomogeneityCalibration;
        _ppCTSMMCapletMaxHomogeneityCalibration = NULL;
    }
}
Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::!CCTSMMCapletMaxHomogeneityCalibration ()
{
    if (_ppCTSMMCapletMaxHomogeneityCalibration != NULL)
    {
	    delete _ppCTSMMCapletMaxHomogeneityCalibration;
    }
}
QuantLib::CTSMMCapletMaxHomogeneityCalibration& Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::GetReference ()
{
    if (_ppCTSMMCapletMaxHomogeneityCalibration == NULL) throw gcnew NativeNullException ();
	return **_ppCTSMMCapletMaxHomogeneityCalibration;
}
boost::shared_ptr<QuantLib::CTSMMCapletMaxHomogeneityCalibration>& Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::GetShared ()
{
    if (_ppCTSMMCapletMaxHomogeneityCalibration == NULL) throw gcnew NativeNullException ();
	return *_ppCTSMMCapletMaxHomogeneityCalibration;
}
QuantLib::CTSMMCapletMaxHomogeneityCalibration* Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::GetPointer ()
{
    if (_ppCTSMMCapletMaxHomogeneityCalibration == NULL) throw gcnew NativeNullException ();
	return &**_ppCTSMMCapletMaxHomogeneityCalibration;
}
#ifdef HANDLE
QuantLib::Handle<QuantLib::CTSMMCapletMaxHomogeneityCalibration>& Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::GetHandle ()
{
	if (_phCTSMMCapletMaxHomogeneityCalibration == NULL)
	{
		_phCTSMMCapletMaxHomogeneityCalibration = new Handle<QuantLib::CTSMMCapletMaxHomogeneityCalibration> (*_ppCTSMMCapletMaxHomogeneityCalibration);
	}
	return *_phCTSMMCapletMaxHomogeneityCalibration;
}
#endif
bool Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::HasNative () 
{
	return (_ppCTSMMCapletMaxHomogeneityCalibration != NULL);
}

UInt32 Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration::CapletMaxHomogeneityCalibration (Cephei::QL::Models::Marketmodels::IEvolutionDescription^ evolution, Cephei::QL::Models::Marketmodels::IPiecewiseConstantCorrelation^ corr, Cephei::IVector<Cephei::QL::Models::Marketmodels::Models::IPiecewiseConstantVariance^>^ displacedSwapVariances, Cephei::IVector<Double>^ capletVols, Cephei::QL::Models::Marketmodels::ICurveState^ cs, Double displacement, Double caplet0Swaption1Priority, UInt64 numberOfFactors, UInt64 maxIterations, Double tolerance, Double deformationSize, Double totalSwaptionError, Cephei::IVector<Cephei::QL::Math::IMatrix^>^ swapCovariancePseudoRoots)
{
    CEvolutionDescription^ _Cevolution;
    CPiecewiseConstantCorrelation^ _Ccorr;
    CoVector<Cephei::QL::Models::Marketmodels::Models::IPiecewiseConstantVariance^>^ _CdisplacedSwapVariances;
    CoVector<Double>^ _CcapletVols;
    CCurveState^ _Ccs;
    CoVector<Cephei::QL::Math::IMatrix^>^ _CswapCovariancePseudoRoots;
    try
    {
    	boost::detail::spinlock::scoped_lock lock (*_pSpinlock);
        _Cevolution = safe_cast<CEvolutionDescription^> (evolution);
        _Cevolution->Lock();
        QuantLib::EvolutionDescription& _evolution = static_cast<QuantLib::EvolutionDescription&> (_Cevolution->GetReference ()); 
        _Ccorr = safe_cast<CPiecewiseConstantCorrelation^> (corr);
        _Ccorr->Lock();
        QuantLib::PiecewiseConstantCorrelation& _corr = static_cast<QuantLib::PiecewiseConstantCorrelation&> (_Ccorr->GetReference ()); 
        _CdisplacedSwapVariances = safe_cast<CoVector<Cephei::QL::Models::Marketmodels::Models::IPiecewiseConstantVariance^>^> (displacedSwapVariances);
        _CdisplacedSwapVariances->Lock();
        INativeVector<Cephei::QL::Models::Marketmodels::Models::IPiecewiseConstantVariance^>^ _NCIdisplacedSwapVariances = _CdisplacedSwapVariances->getFeature (NativeFeature::shared_ptr);
        CPiecewiseConstantVarianceVector^ _NCdisplacedSwapVariances = safe_cast<CPiecewiseConstantVarianceVector^>(_NCIdisplacedSwapVariances);
        std::vector<boost::shared_ptr<
                        QuantLib::PiecewiseConstantVariance> >& _displacedSwapVariances = static_cast<std::vector<boost::shared_ptr<
                        QuantLib::PiecewiseConstantVariance> >&> (_NCdisplacedSwapVariances->GetShared ());
        _CcapletVols = safe_cast<CoVector<Double>^> (capletVols);
        _CcapletVols->Lock();
        INativeVector<Double>^ _NCIcapletVols = _CcapletVols->getFeature (NativeFeature::Value);
        CDoubleVector^ _NCcapletVols = safe_cast<CDoubleVector^>(_NCIcapletVols);
        std::vector<QuantLib::Volatility>& _capletVols = static_cast<std::vector<QuantLib::Volatility>&> (_NCcapletVols->GetReference ());
        _Ccs = safe_cast<CCurveState^> (cs);
        _Ccs->Lock();
        QuantLib::CurveState& _cs = static_cast<QuantLib::CurveState&> (_Ccs->GetReference ()); 
        QuantLib::Spread _displacement = (QuantLib::Spread)ValueHelper::Convert (displacement);
        QuantLib::Real _caplet0Swaption1Priority = (QuantLib::Real)ValueHelper::Convert (caplet0Swaption1Priority);
        QuantLib::Size _numberOfFactors = (QuantLib::Size)ValueHelper::Convert (numberOfFactors);
        QuantLib::Size _maxIterations = (QuantLib::Size)ValueHelper::Convert (maxIterations);
        QuantLib::Real _tolerance = (QuantLib::Real)ValueHelper::Convert (tolerance);
        QuantLib::Real _deformationSize = (QuantLib::Real)ValueHelper::Convert (deformationSize);
        QuantLib::Real _totalSwaptionError = (QuantLib::Real)ValueHelper::Convert (totalSwaptionError);
        _CswapCovariancePseudoRoots = safe_cast<CoVector<Cephei::QL::Math::IMatrix^>^> (swapCovariancePseudoRoots);
        _CswapCovariancePseudoRoots->Lock();
        INativeVector<Cephei::QL::Math::IMatrix^>^ _NCIswapCovariancePseudoRoots = _CswapCovariancePseudoRoots->getFeature (NativeFeature::Value);
        CMatrixVector^ _NCswapCovariancePseudoRoots = safe_cast<CMatrixVector^>(_NCIswapCovariancePseudoRoots);
        std::vector<QuantLib::Matrix>& _swapCovariancePseudoRoots = static_cast<std::vector<QuantLib::Matrix>&> (_NCswapCovariancePseudoRoots->GetReference ());
    	QuantLib::Natural _rv = (QuantLib::Natural)(*_ppCTSMMCapletMaxHomogeneityCalibration)->capletMaxHomogeneityCalibration ( _evolution,  _corr,  _displacedSwapVariances,  _capletVols,  _cs,  _displacement,  _caplet0Swaption1Priority,  _numberOfFactors,  _maxIterations,  _tolerance,  _deformationSize,  _totalSwaptionError,  _swapCovariancePseudoRoots );   
        UInt32 _nrv = (UInt32)ValueHelper::Convert (_rv);
    	return _nrv;
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown std::exception"));
	}
    finally
    {
        if (_Cevolution != nullptr) _Cevolution->Unlock();
        if (_Ccorr != nullptr) _Ccorr->Unlock();
        if (_CdisplacedSwapVariances != nullptr) _CdisplacedSwapVariances->Unlock();
        if (_CcapletVols != nullptr) _CcapletVols->Unlock();
        if (_Ccs != nullptr) _Ccs->Unlock();
        if (_CswapCovariancePseudoRoots != nullptr) _CswapCovariancePseudoRoots->Unlock();
    }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Factory class

Cephei::QL::Models::Marketmodels::Models::ICTSMMCapletMaxHomogeneityCalibration^ Cephei::QL::Models::Marketmodels::Models::CCTSMMCapletMaxHomogeneityCalibration_Factory::Create (Cephei::QL::Models::Marketmodels::IEvolutionDescription^ evolution, Cephei::QL::Models::Marketmodels::IPiecewiseConstantCorrelation^ corr, Cephei::IVector<Cephei::QL::Models::Marketmodels::Models::IPiecewiseConstantVariance^>^ displacedSwapVariances, Cephei::IVector<Double>^ capletVols, Cephei::QL::Models::Marketmodels::ICurveState^ cs, Double displacement, Microsoft::FSharp::Core::FSharpOption<Double>^ caplet0Swaption1Priority)
{
    return gcnew CCTSMMCapletMaxHomogeneityCalibration ( evolution,  corr,  displacedSwapVariances,  capletVols,  cs,  displacement,  caplet0Swaption1Priority);
}
